﻿using Furion.DynamicApiController;
using Furion.FriendlyException;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Core.Permission
{
    /// <summary>
    /// 权限组定义(根据泛型类定义权限组代码)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class PermissionGroupDefinition<T>
        where T : class
    {
        public PermissionGroupDefinition(PermissionGroupDefinition groupDefinition)
        {
            GroupDefinition = groupDefinition;
        }

        /// <summary>
        /// 权限组定义
        /// </summary>
        public PermissionGroupDefinition GroupDefinition { get; private set; }

        /// <summary>
        /// 添加子权限
        /// </summary>
        /// <param name="action"></param>
        /// <param name="displayName"></param>
        /// <param name="isEnabled"></param>
        /// <returns></returns>
        public virtual PermissionDefinition AddPermission(Expression<Func<T, Delegate>> action, string displayName, bool isEnabled = true)
        {
            // 从表达式中获取委托方法名
            if (action.Body is UnaryExpression unary
                && unary.Operand is MethodCallExpression method
                && method.Object is ConstantExpression constant)
            {
                var methodName = ((dynamic)constant.Value).Name;
                var permissionName = $"{PermissionGroupDefinition.PermissionNamed(methodName)}";
                return GroupDefinition.AddPermission(permissionName, displayName, isEnabled);
            }
            else
            {
                throw Oops.Oh("权限模块注册失败");
            }
        }
    }

    /// <summary>
    /// 权限组定义
    /// </summary>
    public class PermissionGroupDefinition
    {
        /// <summary>
        /// 组名称
        /// </summary>
        public string Name { get; private set; }
        /// <summary>
        /// 显示名称
        /// </summary>
        public string DisplayName { get; private set; }
        /// <summary>
        /// 是否启用
        /// </summary>
        public bool IsEnabled { get; set; }
        /// <summary>
        /// 权限集
        /// </summary>
        public Dictionary<string, PermissionDefinition> Permissions { get; private set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="code"></param>
        /// <param name="displayName"></param>
        /// <param name="isEnabled"></param>
        protected internal PermissionGroupDefinition(string code, string displayName, bool isEnabled = true)
        {
            Name = code;
            DisplayName = displayName;
            Permissions = new Dictionary<string, PermissionDefinition>();
            IsEnabled = isEnabled;
        }

        /// <summary>
        /// 添加权限
        /// <para>
        /// 权限代码会自动追加权限组的代码为前缀
        /// </para>
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="displayName">显示名称</param>
        /// <param name="isEnabled">是否启用</param>
        /// <returns></returns>
        public virtual PermissionDefinition AddPermission(string name, string displayName, bool isEnabled = true)
        {
            // 统一权限名称 分组名称_权限名称
            var permission = new PermissionDefinition(name, displayName, isEnabled);
            Permissions.TryAdd(name, permission);
            return permission;
        }

        /// <summary>
        /// 权限组统一命名
        /// </summary>
        /// <param name="inputName"></param>
        /// <returns></returns>
        public static string PermissionGroupNamed(string inputName)
        {
            var replaceKeys = new string[] { "appservice" };
            foreach (var key in replaceKeys)
            {
                inputName = inputName.Replace(key, "", StringComparison.CurrentCultureIgnoreCase);
            }
            return inputName;
        }

        /// <summary>
        /// 权限统一命名
        /// </summary>
        /// <param name="inputName"></param>
        /// <returns></returns>
        public static string PermissionNamed(string inputName)
        {
            var replaceKeys = new string[] { "async", "get", "paged" };
            foreach (var key in replaceKeys)
            {
                inputName = inputName.Replace(key, "", StringComparison.CurrentCultureIgnoreCase);
            }
            return inputName;
        }
    }
}
